package com.xyzwps.paimon.furina.modules.tag

import com.xyzwps.paimon.furina.common.*
import com.xyzwps.paimon.furina.infra.*
import com.xyzwps.paimon.furina.infra.ParameterType.*
import com.xyzwps.paimon.furina.middleware.AuthMW
import org.springdoc.webmvc.core.fn.SpringdocRouteBuilder.route
import org.springframework.stereotype.Component
import org.springframework.web.servlet.function.RouterFunction
import org.springframework.web.servlet.function.ServerRequest
import org.springframework.web.servlet.function.ServerResponse

@Component
class TagApis(
    private val tagApp: TagApp,
    private val authMW: AuthMW,
) {

    private val shouldAuth: RequestFilter = authMW::shouldAuth

    companion object {
        private const val TAG = "Tag"
    }

    fun router(): RouterFunction<ServerResponse> = route()
        .POST("", acceptJson, hf(shouldAuth, handler = ::createTag)) {
            it.tag(TAG)
                .operationId("create-tag")
                .summary("Create a tag")
                .desc(shouldAuth = true)
                .reqBody(CreateTagPayload::class.java)
                .respOK(SimpleTag::class.java)
        }
        .GET("/search", hf(shouldAuth, handler = ::searchTags)) {
            it.tag(TAG)
                .operationId("search-tags")
                .summary("Search tags")
                .desc(shouldAuth = true)
                .query("domain", description = "Tag domain", example = "1", type = INT32)
                .queryPageSize("Search count")
                .respArray(SimpleTag::class.java)
        }
        .build()

    private fun createTag(req: ServerRequest): JsonResponse {
        val body = req.validatedBody<CreateTagPayload>()
        val tag = tagApp.create(TagDomain.validDomain(body.domain), body.name)
        return JsonResponse().body(SimpleTag(tag))
    }

    private fun searchTags(req: ServerRequest): JsonResponse {
        val domain = req.paramInt("domain") ?: throw AppException(AppErrorCode.SEARCH_PARAM_REQUIRED)
        val size = req.paramPageSize()
        val prefix = req.param("prefix").orElse("")
        TagDomain.validDomain(domain)
        val tags = tagApp.searchTags(domain, prefix, size).map { SimpleTag(it) }
        return JsonResponse().body(tags)
    }
}